import os

from alibabacloud_dysmsapi20170525 import models as dysmsapi_20170525_models
from alibabacloud_dysmsapi20170525.client import Client as Dysmsapi20170525Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_tea_util import models as util_models

from common import constants, exception
from common.LoggerFactory import Log
from config import configuration


class AlibabaSmsClient:
    """
    请确保代码运行环境设置了以下访问密钥的环境变量，该访问密钥应该具备管理短信服务（SMS）的权限
    """
    __access_key_id = "ALIBABA_CLOUD_ACCESS_KEY_ID"
    __access_key_secret = "ALIBABA_CLOUD_ACCESS_KEY_SECRET"

    @staticmethod
    def create_client(endpoint) -> Dysmsapi20170525Client:
        """
        使用AK&SK初始化账号Client
        """
        try:
            access_key_id = os.environ[AlibabaSmsClient.__access_key_id]
            access_key_secret = os.environ[AlibabaSmsClient.__access_key_secret]
        except KeyError:
            raise exception.CheckedException("系统未配置阿里的访问密钥")
        config = open_api_models.Config(
            access_key_id=access_key_id,
            access_key_secret=access_key_secret
        )
        config.endpoint = endpoint
        return Dysmsapi20170525Client(config)


class AlibabaSmsSDK:
    success_code = "OK"
    # 接收短信的手机号码，暂时通过环境变量配置
    __phone_numbers = 'ALIBABA_CLOUD_PHONE_NUMBERS'

    def __init__(self, endpoint):
        self.__client = AlibabaSmsClient.create_client(endpoint)

    def send_sms(self, context, template_code, params):
        """
        发送短息
        """
        sign_name = context.get(configuration.SMS_SIGN_NAME_ATT)
        c_phone_numbers = context.get(configuration.SMS_PHONE_NUMBERS_ATT)
        phone_numbers = self.get_phones(c_phone_numbers)
        if len(phone_numbers) == 0:
            Log.console().error("终止短信发送！原因是未配置任何接收短信的号码。")
            raise exception.CheckedException("未配置任何接收短信的号码")
        phone_number = phone_numbers[0]
        send_sms_request = dysmsapi_20170525_models.SendSmsRequest(
            sign_name=sign_name,
            template_code=template_code,
            phone_numbers=phone_number,
            template_param=str(params)
        )
        runtime = util_models.RuntimeOptions()
        resp = self.__client.send_sms_with_options(send_sms_request, runtime)
        self.err_resp(resp, phone_number)

    def send_batch_sms(self, context, template_code, params):
        """
        批量发送短信
        """
        sign_name = context.get(configuration.SMS_SIGN_NAME_ATT)
        phone_numbers = self.get_phones(configuration.SMS_PHONE_NUMBERS_ATT)
        if len(phone_numbers) == 0:
            Log.console().error("终止短信发送！原因是未配置任何接收短信的号码。")
            raise exception.CheckedException("未配置任何接收短信的号码")
        send_batch_sms_request = dysmsapi_20170525_models.SendBatchSmsRequest(
            sign_name_json=f'[{sign_name}]',
            template_code=template_code,
            phone_number_json=str(phone_numbers),
            template_param_json=f'[{params}]'
        )
        runtime = util_models.RuntimeOptions()
        resp = self.__client.send_batch_sms_with_options(send_batch_sms_request, runtime)
        self.err_resp(resp, phone_numbers)

    @classmethod
    def get_phones(cls, phone_numbers):
        """
        获取电话号码
        优先级：调用端 > 配置 > 系统变量
        :param phone_numbers: 调用端传递的号码
        :return:
        """
        if phone_numbers and len(phone_numbers) > 0:
            return phone_numbers
        if len(configuration.SMS_PHONE_NUMBERS) != 0:
            return configuration.SMS_PHONE_NUMBERS
        phone_number = os.environ.get(cls.__phone_numbers)
        if phone_number:
            return phone_number.split(constants.COMMA_SPLICE)
        return ""

    @classmethod
    def err_resp(cls, resp, phone):
        if resp.status_code != 200:
            raise exception.CheckedException(f"短信发送失败！状态码：{resp.status_code}")
        elif resp.body.code == cls.success_code:
            Log.file().debug(f"成功发送短信通知到{phone}")
        else:
            raise exception.CheckedException(f"短信发送失败！{resp.body.message}")
